/**
 * @title 合约交互脚本
 * @description 用于与已部署的SimpleERC20和SimpleNFT合约进行交互
 */
async function main() {
  /**
   * 获取账户列表
   * ethers.getSigners() 返回Hardhat环境中的账户列表
   * owner: 部署者账户
   * addr1: 第一个测试账户（用于接收ERC20转账）
   * addr2: 第二个测试账户（用于接收NFT转移）
   */
  // 获取当前账户
  const [owner, addr1, addr2] = await ethers.getSigners();
  console.log(`使用账户: ${owner.address}`);
  
  // 加载已部署的合约
  console.log("正在加载合约...");
  
  // 已更新为实际部署的合约地址
  const erc20Address = "0x5FbDB2315678afecb367f032d93F642f64180aa3";
  const nftAddress = "0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512";
  
  /**
   * 获取合约实例
   * 1. 先获取合约工厂
   * 2. 然后通过attach连接到已部署的合约地址
   */
  // 获取合约实例
  const SimpleERC20 = await ethers.getContractFactory("SimpleERC20");
  const SimpleNFT = await ethers.getContractFactory("SimpleNFT");
  
  const erc20Contract = await SimpleERC20.attach(erc20Address);
  const nftContract = await SimpleNFT.attach(nftAddress);
  
  console.log(`ERC20合约地址: ${erc20Contract.address}`);
  console.log(`NFT合约地址: ${nftContract.address}`);
  
  // 演示ERC20合约交互
  console.log("\n=== ERC20合约交互演示 ===");
  
  /**
   * 查询ERC20代币信息
   * 通过合约实例调用合约的公共方法获取代币基本信息
   */
  // 查询代币信息
  const name = await erc20Contract.name();
  const symbol = await erc20Contract.symbol();
  const decimals = await erc20Contract.decimals();
  const totalSupply = await erc20Contract.totalSupply();
  
  console.log(`代币名称: ${name}`);
  console.log(`代币符号: ${symbol}`);
  console.log(`代币精度: ${decimals}`);
  /**
   * ethers.utils.formatUnits() 用于将包含精度的大数值转换为可读格式
   * 参数1: 大数值
   * 参数2: 精度
   */
  console.log(`总供应量: ${ethers.utils.formatUnits(totalSupply, decimals)} ${symbol}`);
  
  // 查询余额
  const ownerBalance = await erc20Contract.balanceOf(owner.address);
  console.log(`部署者余额: ${ethers.utils.formatUnits(ownerBalance, decimals)} ${symbol}`);
  
  // 转账演示
  /**
   * ethers.utils.parseUnits() 用于将可读格式的数值转换为包含精度的大数值
   * 参数1: 可读数值
   * 参数2: 精度
   */
  const transferAmount = ethers.utils.parseUnits("100", decimals);
  console.log(`\n向 ${addr1.address} 转账 ${ethers.utils.formatUnits(transferAmount, decimals)} ${symbol}`);
  
  // 调用ERC20合约的transfer方法进行转账
  const tx = await erc20Contract.transfer(addr1.address, transferAmount);
  console.log(`交易哈希: ${tx.hash}`);
  // 等待交易被确认
  await tx.wait();
  
  // 查询转账后的余额
  const newOwnerBalance = await erc20Contract.balanceOf(owner.address);
  const addr1Balance = await erc20Contract.balanceOf(addr1.address);
  
  console.log(`转账后部署者余额: ${ethers.utils.formatUnits(newOwnerBalance, decimals)} ${symbol}`);
  console.log(`接收者余额: ${ethers.utils.formatUnits(addr1Balance, decimals)} ${symbol}`);
  
  // 演示NFT合约交互
  console.log("\n=== NFT合约交互演示 ===");
  
  // 查询NFT信息
  const nftName = await nftContract.name();
  const nftSymbol = await nftContract.symbol();
  const baseURI = await nftContract.baseURI();
  
  console.log(`NFT名称: ${nftName}`);
  console.log(`NFT符号: ${nftSymbol}`);
  console.log(`基础URI: ${baseURI}`);
  
  // 铸造NFT
  console.log(`\n向 ${owner.address} 铸造一个NFT`);
  const mintTx = await nftContract.mintNFT(owner.address);
  console.log(`铸造交易哈希: ${mintTx.hash}`);
  // 等待交易被确认并获取交易收据
  const receipt = await mintTx.wait();
  
  /**
   * 从交易事件中提取NFT ID
   * 铸造NFT会触发Transfer事件，其中包含铸造的NFT ID
   */
  // 获取铸造的NFT ID
  let tokenId = null;
  for (const event of receipt.events) {
    if (event.event === "Transfer") {
      tokenId = event.args.tokenId.toString();
      break;
    }
  }
  
  console.log(`铸造的NFT ID: ${tokenId}`);
  
  // 查询NFT拥有者
  const ownerOfToken = await nftContract.ownerOf(tokenId);
  console.log(`NFT ${tokenId} 的拥有者: ${ownerOfToken}`);
  
  // 查询NFT URI
  const tokenURI = await nftContract.tokenURI(tokenId);
  console.log(`NFT ${tokenId} 的URI: ${tokenURI}`);
  
  // 转移NFT
  console.log(`\n将NFT ${tokenId} 转移给 ${addr2.address}`);
  // 调用NFT合约的transferFrom方法转移NFT
  const transferNFTTx = await nftContract.transferFrom(owner.address, addr2.address, tokenId);
  console.log(`转移交易哈希: ${transferNFTTx.hash}`);
  // 等待交易被确认
  await transferNFTTx.wait();
  
  // 查询转移后的NFT拥有者
  const newOwnerOfToken = await nftContract.ownerOf(tokenId);
  console.log(`转移后NFT ${tokenId} 的拥有者: ${newOwnerOfToken}`);
}

// 执行主函数
main()
  .then(() => process.exit(0)) // 成功时退出进程
  .catch((error) => { // 捕获并打印错误
    console.error(error);
    process.exit(1);
  });